package dmir.reaction.publico.parsers;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.google.common.collect.Multimap;

import dmir.reaction.publico.xml.Article;
import dmir.reaction.publico.xml.Entity;
import dmir.reaction.publico.xml.EntityPair;

public class ArticleParserCoOccurrences extends DefaultHandler {
	
	String data = new String();
	String year_month = new String();
	boolean getDate = false;
	boolean getTime = false;
	boolean getEntities = false;
	int discarded_count = 0;
	
	String article_date = new String();
	String id;
	String date;
	String time;
	String category = new String();
	String url = new String();

	Multimap<EntityPair, Article> coOccurrences = com.google.common.collect.HashMultimap.create();	
	
	/* keep the unique entities that occur in the article */
	Set<Entity> entitiesSet = new HashSet<Entity>();
	
	/* global counter of frequency of each entity in the whole corpus of news */
	HashMap<Entity,Integer> entities = new HashMap<Entity, Integer>();	
	
	/* external mappings of unique entities to ids */
	HashMap<String, Integer> entities_ids;

	Logger logger = Logger.getLogger(ArticleParserCoOccurrences.class);
	
	private static Logger discarded = Logger.getLogger("entity discarded: " + ArticleParserCoOccurrences.class.getName() );
	
		
	public ArticleParserCoOccurrences(String year_month, HashMap<String, Integer> entities_ids) {
		super();
		this.year_month = year_month;
		logger.info("Year Month: " + this.year_month);
		this.entities_ids = entities_ids;
	}
	
	public void listCoOccurrences(Article article) {
						
		LinkedList<Entity> entitiesList = new LinkedList<Entity>(article.entities); 
		
		for (int i = 0; i < entitiesList.size(); i++) {
			for (int j = 0; j < entitiesList.size(); j++) {
				if (j==i)
					continue;
				else {						
					System.out.println(							
							String.valueOf(entitiesList.get(i).id) + ':' + entitiesList.get(i).etype + ':' + entitiesList.get(i).ename + '\t' + 
							String.valueOf(entitiesList.get(j).id) + ':' + entitiesList.get(j).etype + ':' + entitiesList.get(j).ename + '\t' + 
							article.category + '\t'+ article.date + '\t' + article.time + '\t' + article.id + '\t' + article.url);
				}
			}
		}
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase("date")) {
			getDate = true;
			this.data = "";
		}
		
		if (qName.equalsIgnoreCase("time")) {
			getTime = true;
			this.data = "";
		}
		
		if (qName.equalsIgnoreCase("article")) {
			this.id = attributes.getValue(0);
			this.category = attributes.getValue(1);
			this.url = attributes.getValue(2);
		}
	}

	public void characters(char ch[], int start, int length)
			throws SAXException {

		if (getDate || getEntities || getTime) {
			this.data = new String(ch, start, length);
		}
	}

	public void endElement(String uri, String localName, String qName) throws SAXException {

		if (getDate) {
			this.getDate = false;
			this.date = this.data;
						
			/* ignore articles from 2000 and 2011 */			
			if (!(this.data.startsWith("2000") || (this.data.startsWith("2011")))) {				
				if (!this.year_month.equalsIgnoreCase("ALL")) {
					if (this.data.matches(year_month + ".*")) {
						getEntities = true;
					}				
				}
				
				else if (this.year_month.equalsIgnoreCase("ALL")) {
					getEntities = true;
				}				
			}
		}
		
		
		if (getTime) {
			this.getTime = false;
			this.time = this.data;			
		}
		

		if (qName.equalsIgnoreCase("PESSOA") && getEntities) {
			
			int id;
			
			try {
				
				/* get the identifier and create an Entity object*/			
				id = entities_ids.get(this.data);								
				Entity entity = new Entity("PER", this.data, id);				
				/* keep the number of occurrences for this entity in this article */
				try {					
					this.entities.put(entity, this.entities.get(entity)+1);
				} 
				catch (Exception e) {
					this.entities.put(entity, 1);
				}
				
				entitiesSet.add(entity);
				
			} catch (Exception e1) {				
				/* if not in the entities with identifier discarded */				
				discarded.info("Entity PESSOA discarded: " + this.data.trim());	
				this.discarded_count++;
			}
		}
		
		
		if (qName.equalsIgnoreCase("article") && getEntities) {
			
			this.getDate = false;
			this.getEntities = false;			
			Article article = new Article(Integer.parseInt(this.id), this.category, this.date, this.time, this.url, entitiesSet);
			listCoOccurrences(article);
			entitiesSet.clear();
		}
		
		if (qName.equalsIgnoreCase("root")) {
			logger.info("Total discarded, garbage: " + this.discarded_count);
			
			/* write to file the global frequency of all entities */
			
			FileWriter w = null;
			
			try {
				w = new FileWriter(new File("entities_freq.txt"));
				
				for (Entity e : this.entities.keySet()) {
					w.write(String.valueOf(e.id) + ':' + e.etype + ':' + e.ename + '\t' + entities.get(e) + '\n');
				}
				w.close();
				
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}